package edu.sjb.map;

import org.ini4j.Ini;
import org.ini4j.InvalidFileFormatException;

import edu.sjb.AppLauncher;

public abstract class MapLoader {

	//Generic place entities
    public static final int EMPTY 		    = 0x30; //'0'
    public static final int BOTTOMLESS_PIT  = 0x50; //'P'
    public static final int GOAL			= 0x47; //'G'
    
    //Actor's starting points
    public static final int MARIO_START		= 0x6d; //'m'
    public static final int GOOMBA_START	= 0x67; //'g'
    public static final int KOOPA_START		= 0x6b; //'k'
    
    //Bricks
    public static final int BRICK		    = 0x80;
    public static final int MASK_00COINS    = 0x00;
    public static final int MASK_01COINS    = 0x01;
    public static final int MASK_10COINS    = 0x02;
    public static final int MASK_MUSHROOM   = 0x03;
    public static final int MASK_FLOWER     = 0x04;
    public static final int MASK_STAR       = 0x05;
    public static final int MASK_MUSH1UP    = 0x06;
    public static final int MASK_NUCBOMB    = 0x07;
    public static final int MASK_IS_SOLID   = 0x10;
    public static final int MASK_IS_QM      = 0x20;
    public static final int MASK_OPAQUE     = 0x40;		
    

    public static Map loadMapFromIni(Ini iniFile) throws InvalidFileFormatException {
        if (iniFile.keySet().contains("Level")
                && iniFile.keySet().contains("Description")
                && iniFile.keySet().contains("LevelData")) {
            Map result = new Map(
                    iniFile.get("Description", "Width", int.class),
                    iniFile.get("Description", "Heigth", int.class));
            parseFile(iniFile, result);
            return result;
        } else {
            throw new InvalidFileFormatException("SJL file is invalid or incomplete,"
                    + "some data is missing!");
        }
    }

    private static void parseFile(Ini f,
            Map m) {
        int i = 0;
        for (String element : f.get("LevelData").keySet()) {
            String str = f.get("LevelData", element, String.class);
            int[] splitStr = splitString(str);
			parseLine(i, splitStr, m);
            i++;
        }
    }


	private static void parseLine(int line,
            int[] str,
            Map m) {
        for (int column = 0; column < str.length; column++) {
        	int currChar = str[column];
        	if (currChar<BRICK) {
	            switch (currChar) {
	                case EMPTY:
	                    m.setElementAt(
	                            line,
	                            column,
	                            GenericMapElementFactory.emptySpace()
	                        );
	                    break;
	                case BOTTOMLESS_PIT:
	                	m.setElementAt(
	                			line,
	                			column,
	                			GenericMapElementFactory.bottomlessPit()
	                		);
	                	break;
	                case GOAL:
	                	m.setElementAt(
	                			line,
	                			column,
	                			GenericMapElementFactory.goalEntity()
	                		);
	                	break;
	                case MARIO_START:
	                	int posX = 8;
	                	int posY = 8;
	                	AppLauncher.GUI().mario().setPositionX(posX);
	                	AppLauncher.GUI().mario().setPositionY(posY);
	                	m.setElementAt(
	                            line,
	                            column,
	                            GenericMapElementFactory.emptySpace()
	                        );
	                	break;
	                default:
	                    throw new IllegalArgumentException(
	                            "Entered characer doesn't correspond to any existing! " +
	                            String.format("(Entity %c @ pos %d:%d)", str[column], column, line));
	            }
        	}
        	else {
        		m.setElementAt(line, column, GenericMapElementFactory.brick(currChar & 0x7f));
        	}
        }
    }
    
	private static int[] splitString(String str) {
		final String hexChars = "0123456789abcdef";
		int[] res = new int[str.length() / 2];
		for (int i = 0; i < res.length; i++) {
			res[i] = hexChars.indexOf(Character.toLowerCase(str.charAt(2 * i))) * 16
					 + hexChars.indexOf(Character.toLowerCase(str.charAt(2 * i + 1)));
		}
		return res;
	}
}
